#include "Config.h"
#include "core/CLua.h"
#include "platform/PlatUtil.h"

/*********************************************************************************************************/
/*********************************************************************************************************/
bool Config::Released;

bool Config::TestCase_AsPretendedSQEnv;

bool Config::TestCase_SampleDataEnabled;
int Config::TestCase_SampleDataLoopIntervalMs;

int Config::Version_Code;
CString Config::Version_CachePath;

bool Config::Enable_Log;

int Config::Mechanism_ExpireUpdateCnt;
int Config::Mechanism_ExpireFrameCnt;
int Config::View3D_W;
int Config::View3D_H;
int Config::View3D_SkylineFromTopPx;
int Config::View3D_FadeOffsetHorizonPx;
int Config::View3D_FadeOffsetSkylinePx;
CString Config::View3D_BgLightImgPath;
CString Config::View3D_BgDarkImgPath;
CString Config::View3D_ZhichePngPath;
CString Config::View3D_ZhicheInfoPath;
float Config::View3D_ZhichePngOccupationWRate;
float Config::View3D_ZhichePngOccupationHRate;

CColor Config::Render_ClearColor;

float Config::Render_SurfaceSSAA;
int Config::Render_SurfaceSamples;

float Config::Camera_ViewScale;
P3D Config::Camera_Position;
float Config::Camera_PitchAngle;
float Config::Camera_FOV;
float Config::Camera_YawAngle;
float Config::Camera_NearPlane;
float Config::Camera_FarPlane;

CColor Config::Light_GlobalAmbient_Color;

P3D Config::Light_Directional_WorldDirection;
float Config::Light_Directional_Intensity;
CColor Config::Light_Directional_Color;

P3D Config::Light_Point_Position;
float Config::Light_Point_Intensity;
float Config::Light_Point_ConstAtt;
float Config::Light_Point_LinearAtt;
float Config::Light_Point_QuadAtt;
CColor Config::Light_Point_Color;

bool Config::Material_ForceUseCfgValue;
float Config::Material_Metallic;
float Config::Material_Roughness;
CColor Config::Material_BaseColor;
float Config::Material_PBRGlobalAmbientCompnt;

CString Config::Shader_Dir;
CString Config::Shader_Line;
CString Config::Shader_ModelPBR;
CString Config::Shader_AnyFree;
CString Config::Shader_AnyFreeAlpha;
CString Config::Shader_AccFD;
CString Config::Shader_AccTG;
CString Config::Shader_LampLight;
CString Config::Shader_LineEllipse;
CString Config::Shader_DclcArrow;
CString Config::Shader_RoadDotBg;
CString Config::Shader_LaneBg;
CString Config::Shader_RoadEdge;
CString Config::Shader_SceneTexture;
CString Config::Shader_ActiveCircle;

bool Config::Line_CutOff_ByEqStart;
bool Config::Line_CutOff_ByEqEnd;
float Config::Line_FadeByEndZOffset;
CColor Config::Line_DefColor;
CColor Config::Line_DefGrey;
float Config::Line_PointsZStep;
float Config::Line_Width;
float Config::Line_HInterval;
float Config::Line_VSpeedFactor;
float Config::Line_Dashed_SegLen;
float Config::Line_Dashed_SegInterval;
float Config::Line_RoadEdgeDashed_SegLen;
float Config::Line_RoadEdgeDashed_SegInterval;
float Config::Line_RoadEdge_Width;
float Config::Line_RoadEdge_Height;
CColor Config::Line_RoadEdge_UpColor;
CColor Config::Line_RoadEdge_SideColor;
RoadEdgeStyle Config::Line_RoadEdge_Style;

CString Config::Model_Dir;
CString Config::Model_Zhiche;
CString Config::Model_Car;
CString Config::Model_Bus;
CString Config::Model_Truck;
CString Config::Model_Moto;
CString Config::Model_Bike;
CString Config::Model_Cone;
CString Config::Model_Person;
CString Config::Model_Barrier;
CString Config::Model_Undefined;

float Config::Marker_AccFD_FrontOffsetD;
float Config::Marker_AccFD_TopWByFrontWTimes;
float Config::Marker_AccFD_BottomWByFrontWTimes;
float Config::Marker_AccFD_HByFrontWTimes;
CColor Config::Marker_AccTG_Color;
float Config::Marker_ACCTG_ZhicheHeadOffsetD;
float Config::Marker_AccTG_WByZhicheWTimes;
float Config::Marker_AccTG_RectHByZhicheWTimes;
float Config::Marker_AccTG_RectIntervalByZhicheWTimes;
float Config::Marker_Lamp_LightRadiusByModelWTimes;
CColor Config::Marker_Lamp_TurnColor;
CColor Config::Marker_Lamp_BrakeColor;
float Config::Marker_Ellipse_CenterZ;
float Config::Marker_Ellipse_HAxis;
float Config::Marker_Ellipse_VAxis;
CColor Config::Marker_Ellipse_ColorNormal;
CColor Config::Marker_Ellipse_ColorWarning;
int Config::Marker_Ellipse_BlinkFrameGap;
float Config::Marker_DclcArrow_ZStart;
float Config::Marker_DclcArrow_ZRectEnd;
float Config::Marker_DclcArrow_ZBezierEnd;
float Config::Marker_DclcArrow_ZEndBelowSkyline;
float Config::Marker_DclcArrow_EdgeW;
float Config::Marker_DclcArrow_RectWByZhicheWTimes;
float Config::Marker_DclcArrow_OffsetWPercentage;
CColor Config::Marker_DclcArrow_Color;
float Config::Marker_RoadBg_DotRadius;
float Config::Marker_RoadBg_DotIntervalH;
float Config::Marker_RoadBg_DotIntervalV;
float Config::Marker_RoadBg_PointsZStep;
CColor Config::Marker_RoadBg_LightColor;
CColor Config::Marker_RoadBg_DarkColor;
RoadBgStyle Config::Marker_RoadBg_Style;
int Config::Marker_ActiveCircle_BreathFrameGap;
float Config::Marker_ActiveCircle_Radius;

float Config::Y_RoadBg;
float Config::Y_Line;
float Config::Y_ActiveCircle;
float Config::Y_Model;
float Config::Y_Ellipse;
float Config::Y_DclcArrow;
float Config::Y_AccFD;
float Config::Y_AccTG;

void Config::readConfigFields() {
	auto cfgPath = EmbedEnv_Config_File_Path;
	toLocalEnvPath(cfgPath);

	sol::state lua;
	if (IsProject_KT)
		lua.set("Project", "KT");
	else if (IsProject_SQ)
		lua.set("Project", "SQ");

	std::string content;
	PlatUtil::readFileAsString(content, cfgPath);
	sol::table config;
	bool success = CLua::load(lua, config, content);
	if (!success)
		return;

	/************************************************************************************/
	/************************************************************************************/
	Released = config["released"];

	const auto& TestCase = config["TestCase"];
	TestCase_AsPretendedSQEnv = IsEnv_Linux ? false : TestCase["asPretendedSQEnv"];
	TestCase_SampleDataEnabled = TestCase["sampleData"]["enabled"];
	TestCase_SampleDataLoopIntervalMs = TestCase["sampleData"]["intervalMs"];

	const auto& Version = config["Version"];
	Version_Code = Version["code"];
	Version_CachePath = Version["cachePath"].get<std::string>();
	toLocalEnvPath(Version_CachePath);

	const auto& Log = config["Log"];
	Enable_Log = Log["enabled"];

	const auto& Mechanism = config["Mechanism"];
	Mechanism_ExpireUpdateCnt = Mechanism["expire"]["updateCnt"];
	Mechanism_ExpireFrameCnt = Mechanism["expire"]["frameCnt"];

	const auto& View3D = config["View3D"];
	CLua::parseArray(View3D_W, View3D_H, View3D["size"]);
	View3D_SkylineFromTopPx = View3D["skylineFromTopPx"];
	View3D_FadeOffsetHorizonPx = View3D["fadeOffsetPx"]["horizon"];
	View3D_FadeOffsetSkylinePx = View3D["fadeOffsetPx"]["skyline"];
	View3D_BgLightImgPath = View3D["bgImgPath"]["light"].get<std::string>();
	View3D_BgDarkImgPath = View3D["bgImgPath"]["dark"].get<std::string>();
	View3D_ZhichePngPath = View3D["zhicheCachePath"]["png"].get<std::string>();
	View3D_ZhicheInfoPath = View3D["zhicheCachePath"]["info"].get<std::string>();
	toLocalEnvPath(View3D_BgLightImgPath);
	toLocalEnvPath(View3D_BgDarkImgPath);
	toLocalEnvPath(View3D_ZhichePngPath);
	toLocalEnvPath(View3D_ZhicheInfoPath);
	View3D_ZhichePngOccupationWRate = View3D["zhichePngOccupation"]["wRate"];
	View3D_ZhichePngOccupationHRate = View3D["zhichePngOccupation"]["hRate"];

	const auto& Render = config["Render"];
	Render_ClearColor = Render["clearColor"].get<std::string>();
	Render_SurfaceSamples = Render["surface"]["samples"];
	Render_SurfaceSSAA = Render["surface"]["SSAA"];

	const auto& Camera = config["Camera"];
	Camera_ViewScale = Camera["viewScale"];
	CLua::readAsVec3(Camera_Position, Camera["position"]);
	Camera_PitchAngle = Camera["pitchAngle"];
	Camera_FOV = Camera["fov"];
	Camera_YawAngle = Camera["yawAngle"];
	CLua::parseArray(Camera_NearPlane, Camera_FarPlane, Camera["nearFarPlane"]);

	Light_GlobalAmbient_Color = config["Light"]["globalAmbient"].get<std::string>();

	const auto& LightDirectional = config["Light"]["Directional"];
	CLua::readAsVec3(Light_Directional_WorldDirection, LightDirectional["worldDirection"]);
	Light_Directional_Intensity = LightDirectional["intensity"];
	Light_Directional_Color = LightDirectional["color"].get<std::string>();

	const auto& LightPoint = config["Light"]["Point"];
	CLua::readAsVec3(Light_Point_Position, LightPoint["position"]);
	Light_Point_Intensity = LightPoint["intensity"];
	Light_Point_ConstAtt = LightPoint["constAtt"];
	Light_Point_LinearAtt = LightPoint["linearAtt"];
	Light_Point_QuadAtt = LightPoint["quadAtt"];
	Light_Point_Color = LightPoint["color"].get<std::string>();

	const auto& Material = config["Material"];
	Material_ForceUseCfgValue = Material["forceUseCfgValue"];
	Material_Metallic = Material["metallic"];
	Material_Roughness = Material["roughness"];
	Material_BaseColor = Material["baseColor"].get<std::string>();
	Material_PBRGlobalAmbientCompnt = Material["pbrGlobalAmbientCompnt"];

	const auto& Shader = config["Shader"];
	Shader_Dir = Shader["dir"].get<std::string>();
	toLocalEnvPath(Shader_Dir);
	Shader_Line = Shader["line"].get<std::string>();
	Shader_ModelPBR = Shader["modelPBR"].get<std::string>();
	Shader_AnyFree = Shader["anyFree"].get<std::string>();
	Shader_AnyFreeAlpha = Shader["anyFreeAlpha"].get<std::string>();
	Shader_AccFD = Shader["accFD"].get<std::string>();
	Shader_AccTG = Shader["accTG"].get<std::string>();
	Shader_LampLight = Shader["lampLight"].get<std::string>();
	Shader_LineEllipse = Shader["lineEllipse"].get<std::string>();
	Shader_DclcArrow = Shader["dclcArrow"].get<std::string>();
	Shader_RoadDotBg = Shader["roadDotBg"].get<std::string>();
	Shader_LaneBg = Shader["laneBg"].get<std::string>();
	Shader_RoadEdge = Shader["roadEdge"].get<std::string>();
	Shader_SceneTexture = Shader["sceneTexture"].get<std::string>();
	Shader_ActiveCircle = Shader["activeCircle"].get<std::string>();

	const auto& Line = config["Line"];
	Line_CutOff_ByEqStart = Line["cutOff"]["enableEqStart"];
	Line_CutOff_ByEqEnd = Line["cutOff"]["enableEqEnd"];
	Line_FadeByEndZOffset = Line["fadeByEndZOffset"];
	Line_DefColor = Line["defColor"].get<std::string>();
	Line_DefGrey = Line["defGrey"].get<std::string>();
	Line_PointsZStep = Line["pointsZStep"];
	Line_Width = Line["width"];
	Line_HInterval = Line["hInterval"];
	Line_VSpeedFactor = Line["vSpeedFactor"];
	Line_Dashed_SegLen = Line["dashed"]["segLen"];
	Line_Dashed_SegInterval = Line["dashed"]["segInterval"];
	CLua::parseArray(Line_RoadEdge_Width, Line_RoadEdge_Height, Line["roadEdge"]["size"]);
	Line_RoadEdge_UpColor = Line["roadEdge"]["upColor"].get<std::string>();
	Line_RoadEdge_SideColor = Line["roadEdge"]["sideColor"].get<std::string>();
	if (IsProject_SQ || TestCase_AsPretendedSQEnv)
		Line_RoadEdge_Style = RoadEdgeStyle::Continuous;
	else {
		Line_RoadEdge_Style = RoadEdgeStyle::Dashed;
		Line_RoadEdgeDashed_SegLen = Line["roadEdge"]["segLen"];
		Line_RoadEdgeDashed_SegInterval = Line["roadEdge"]["segInterval"];
	}

	const auto& Model = config["Model"];
	Model_Dir = Model["dir"].get<std::string>();
	toLocalEnvPath(Model_Dir);
	Model_Zhiche = Model["zhiche"].get<std::string>();
	Model_Car = Model["car"].get<std::string>();
	Model_Bus = Model["bus"].get<std::string>();
	Model_Truck = Model["truck"].get<std::string>();
	Model_Moto = Model["moto"].get<std::string>();
	Model_Bike = Model["bike"].get<std::string>();
	Model_Cone = Model["cone"].get<std::string>();
	Model_Person = Model["person"].get<std::string>();
	Model_Barrier = Model["barrier"].get<std::string>();
	Model_Undefined = Model["undefined"].get<std::string>();

	const auto& Marker = config["Marker"];
	Marker_AccFD_FrontOffsetD = Marker["accFD"]["frontOffsetD"];
	Marker_AccFD_TopWByFrontWTimes = Marker["accFD"]["topWByFrontWTimes"];
	Marker_AccFD_BottomWByFrontWTimes = Marker["accFD"]["bottomWByFrontWTimes"];
	Marker_AccFD_HByFrontWTimes = Marker["accFD"]["hByFrontWTimes"];
	Marker_AccTG_Color = Marker["accTG"]["color"].get<std::string>();
	Marker_ACCTG_ZhicheHeadOffsetD = Marker["accTG"]["zhicheHeadOffsetD"];
	Marker_AccTG_WByZhicheWTimes = Marker["accTG"]["wByZhicheWTimes"];
	Marker_AccTG_RectHByZhicheWTimes = Marker["accTG"]["rectHByZhicheWTimes"];
	Marker_AccTG_RectIntervalByZhicheWTimes = Marker["accTG"]["rectIntervalByZhicheWTimes"];
	Marker_Lamp_LightRadiusByModelWTimes = Marker["lamp"]["lightRadiusByModelWTimes"];
	Marker_Lamp_TurnColor = Marker["lamp"]["turnColor"].get<std::string>();
	Marker_Lamp_BrakeColor = Marker["lamp"]["brakeColor"].get<std::string>();
	Marker_Ellipse_CenterZ = Marker["ellipse"]["centerZ"];
	Marker_Ellipse_HAxis = Marker["ellipse"]["hAxis"];
	Marker_Ellipse_VAxis = Marker["ellipse"]["vAxis"];
	Marker_Ellipse_ColorNormal = Marker["ellipse"]["colorNormal"].get<std::string>();
	Marker_Ellipse_ColorWarning = Marker["ellipse"]["colorWarning"].get<std::string>();
	Marker_Ellipse_BlinkFrameGap = Marker["ellipse"]["blinkFrameGap"];
	Marker_DclcArrow_ZStart = Marker["dclcArrow"]["zStart"];
	Marker_DclcArrow_ZRectEnd = Marker["dclcArrow"]["zRectEnd"];
	Marker_DclcArrow_ZBezierEnd = Marker["dclcArrow"]["zBezierEnd"];
	Marker_DclcArrow_ZEndBelowSkyline = Marker["dclcArrow"]["zEndBelowSkyline"];
	Marker_DclcArrow_EdgeW = Marker["dclcArrow"]["edgeW"];
	Marker_DclcArrow_RectWByZhicheWTimes = Marker["dclcArrow"]["rectWByZhicheWTimes"];
	Marker_DclcArrow_OffsetWPercentage = Marker["dclcArrow"]["offsetWPercentage"];
	Marker_DclcArrow_Color = Marker["dclcArrow"]["color"].get<std::string>();
	if (IsProject_SQ || TestCase_AsPretendedSQEnv) {
		Marker_RoadBg_PointsZStep = Marker["roadBg"]["zStep"];
		Marker_RoadBg_LightColor = Marker["roadBg"]["color"]["light"].get<std::string>();
		Marker_RoadBg_DarkColor = Marker["roadBg"]["color"]["dark"].get<std::string>();
		Marker_RoadBg_Style = RoadBgStyle::Fill;
	} else {
		Marker_RoadBg_DotRadius = Marker["roadBg"]["dotRadius"];
		Marker_RoadBg_DotIntervalH = Marker["roadBg"]["dotInterval"]["h"];
		Marker_RoadBg_DotIntervalV = Marker["roadBg"]["dotInterval"]["v"];
		Marker_RoadBg_LightColor = Marker["roadBg"]["color"]["light"].get<std::string>();
		Marker_RoadBg_DarkColor = Marker["roadBg"]["color"]["dark"].get<std::string>();
		Marker_RoadBg_Style = RoadBgStyle::DotMatrix;
	}
	Marker_ActiveCircle_BreathFrameGap = Marker["activeCircle"]["breathFrameGap"];
	Marker_ActiveCircle_Radius = Marker["activeCircle"]["radius"];

	const auto& Y = config["Y"];
	Y_RoadBg = Y["roadBg"];
	Y_Line = Y["line"];
	Y_ActiveCircle = Y["activeCircle"];
	Y_Model = Y["model"];
	Y_Ellipse = Y["ellipse"];
	Y_DclcArrow = Y["dclcArrow"];
	Y_AccFD = Y["accFD"];
	Y_AccTG = Y["accTG"];
}